<?php

namespace app\admin\controller;

use app\admin\model\Plugin as PluginModel;
use app\BaseController;
use think\facade\Db;
use think\facade\Filesystem;
use think\Request;

class Plugin extends BaseController
{
    public function index()
    {
        return view();
    }

    public function list_data()
    {
        $users = new PluginModel;
        $limit = input('limit');
        $users = $users->paginate($limit);
        return lay_data($users);
    }

    public function upload(Request $request)
    {
        try {
            $file = $request->file('plugin');

            /*判断格式*/
            $type = explode('.', $file->getOriginalName());
            if (!in_array(end($type), ['zip', 'rar'])) {
                return msg_error('只能上传zip和rar格式的文件');
            }
            /*判断格式end*/

            /*上传压缩包*/
            $savename = Filesystem::putFile('file', $file);
            $url      = 'upload/' . $savename;
            if (!$savename) {
                return msg_error('保存异常');
            }
            /*上传压缩包end*/

            /*解压*/
            $zipFile = new \PhpZip\ZipFile();
            $zipFile->openFile($url);

//            $dir = 'upload/plugin/';
            $dir = app()->getRootPath().'/plugin';
            if (!is_dir($dir)) {
                mkdir($dir, 0777, true);
            }
            // 临时
            $info = $zipFile->extractTo($dir);

            //插件目录
            $get_folders = folder_list($dir);
            /*判断插件是否符合要求*/
            $check = $this->check_plugin($get_folders);
            if ($check) {
                return msg_error($check);
            }
            /*判断插件是否符合要求end*/

            // 移动插件
            $this->move_plugin($get_folders,$dir);
            /*解压end*/

            /*删除临时插件*/
//            deldir($dir);
            /*删除临时插件*/

            return msg_success('上传成功',$info);

        } catch (\Exception $e) {
            return msg_error($e->getMessage());
        }
    }


    /*判断插件是否符合要求*/
    protected function check_plugin($get_folders)
    {
        try {
            if (!isset($get_folders[0]['name'])) {
                return '插件配置文件不存在';
            }
            if (!isset($get_folders[0]['child']) || count($get_folders[0]['child']) < 1) {
                return '插件格式错误';
            }
            $name = $get_folders[0]['name'];
            $str  = $name . '/config.json';
            if (!is_file($str)) {
                return '插件配置文件不存在';
            }

            $get_plugin_json = file_get_contents($str);
            $config          = json_decode($get_plugin_json, true);

            /*配置文件格式*/
            $config_field = [
                'title', 'name', 'description', 'version','nav','set'
            ];
            if ($config_field != array_keys($config)) {
                return '配置文件错误';
            }
            //当前配置

            $config_uri = app()->getRootPath() . '/app/plugin/config/' . $config['name'] . '.json';
            if (is_file($config_uri)) {
                $get_plugin_json = file_get_contents($config_uri);
                $get_plugin      = json_decode($get_plugin_json, true);
                /*判断版本*/
                if ($get_plugin['version'] == $config['version']) {
                    return '已经安装当前版本';
                }
                if ($get_plugin['version'] > $config['version']) {
                    return '不能安装低版本插件';
                }
                /*判断版本end*/
            }
            /*样式*/

            foreach ($get_folders[0]['child'] as $folder){
                $array       = explode('/', $folder['name']);
                $folder_name = end($array);
                if($folder_name == 'static'){
                    /*判断是否存在样式文件*/
                    $has_style = false;
                    foreach ($folder['child'] as $item){
                        $c_array       = explode('/', $item['name']);
                        $c_folder_name = end($c_array);
                        if($c_folder_name == 'style.css'){
                            $has_style = true;
                        }
                    }
                    if(!$has_style){
                        return 'static下不存在style.css样式文件';
                    }
                    /*判断是否存在样式文件*/
                }

                /*导入数据库*/

                if($folder_name == 'model'){
                    /*判断是否存在数据库是否存在表*/
                    foreach ($folder['child'] as $item){
                        $c_array       = explode('/', $item['name']);
                        $c_folder_name = end($c_array);
                        $explode       = explode('.', $c_folder_name);
                        $model_name    = $explode[0];
                        $model = Db::name($model_name)->select();
                        if(!$model){
                            return '表异常，请检查对应的表';
                        }
                    }
                    /*判断是否存在数据库是否存在表*/
                }
            }

            return false;
        } catch (\Exception $e) {
            if(substr($e->getMessage(),'0','15') == 'SQLSTATE[42S02]'){
                $message = $e->getMessage();
                $start = '1146 Table';
                $end = "doesn't exist";
                $msg = $this->get_between($message,$start,$end);
                return '对应的表不存在('. trim($msg) .'),请先导入，sql文件在压缩包中sql文件夹中';
            }else{
                return $e->getMessage();
            }
        }
    }
    protected function get_between($input, $start, $end) {
        $substr = substr($input, strlen($start)+strpos($input, $start),(strlen($input) - strpos($input, $end))*(-1));
        return $substr;
    }

    /*移动文件*/
    protected function move_plugin($folder,$dir)
    {
        try {
            $name = $folder[0]['name'];
            $str  = $name . '/config.json';
            if (!is_file($str)) {
                return '插件配置文件不存在';
            }
            $get_plugin_json = file_get_contents($str);
            $config          = json_decode($get_plugin_json, true);


            /*配置文件*/
            $plugin_name = $config['name'];
            $pluginPath = app()->getRootPath().'/app/plugin/';
            $staticPath = app()->getRootPath().'/public/plugin';
            $upload_plugin = $dir .'/'. $plugin_name;

            $plugin_config_url     = $pluginPath . 'config/';
            if(!file_exists($plugin_config_url)){
                dir_mkdir($plugin_config_url);
            }
            copy($str, $plugin_config_url . $plugin_name .'.json');

            $child = $folder[0]['child'];
            foreach ($child as $value) {
                /*控制器*/
                if ($value['name'] == $upload_plugin . '/controller') {
                    $pluginController = $pluginPath . 'controller/'.$plugin_name;
                    if(!file_exists($pluginController)){
                        dir_mkdir($pluginController);
                    }
                    foreach ($value['child'] as $item){
                        $array = explode('/', $item['name']);
                        copy($item['name'], $pluginController. '/' .end($array));
                    }
                }

                /*路由*/
                if ($value['name'] == $upload_plugin  . '/route') {
                    $pluginRoute = $pluginPath . 'route/list/';
                    if(!file_exists($pluginRoute)){
                        dir_mkdir($pluginRoute);
                    }
                    copy($value['child'][0]['name'], $pluginRoute . $plugin_name .'.json');
                }

                /*模型*/
                if ($value['name'] == $upload_plugin  . '/model') {
                    $model_uri = $pluginPath . 'model/' . $plugin_name;
                    if(!file_exists($model_uri)) {
                        dir_mkdir($model_uri);
                    }
                    foreach ($value['child'] as $item){
                        $array = explode('/', $item['name']);
                        copy($item['name'], $model_uri. '/' .end($array));
                    }
                }

                /*视图*/
                if ($value['name'] == $upload_plugin  . '/view') {
                    $pluginView = $pluginPath . 'view/';
                    dir_copy($value['name'], $pluginView . $plugin_name);
                }

                /*资源*/
                if ($value['name'] == $upload_plugin  . '/static') {
                    if(!file_exists($staticPath)) {
                        dir_mkdir($staticPath);
                    }
                    dir_copy($value['name'], $staticPath .'/'. $plugin_name);
                }
            }

            /*新建插件*/
            $Plugin = PluginModel::where(['name'=>$config['name']])->find();
            if($Plugin){
                $Plugin->title = $config['title'];
                $Plugin->description = $config['description'];
                $Plugin->version = $config['version'];
                $Plugin->setting = $config['set'];
                $Plugin->save();
            }else{
                $plugin_data = [
                    'title'=>$config['title'],
                    'name'=>$config['name'],
                    'description'=>$config['description'],
                    'version'=>$config['version'],
                    'setting'=>$config['set'],
                    'frozen'=>0,
                ];
                $Plugin = PluginModel::create($plugin_data);
            }
            /*新建插件end*/

            return $Plugin;

        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }

    public function plugin_update($id)
    {
        /*删除现有插件*/
        $plugin = PluginModel::find($id);
        $path = app()->getRootPath() . 'app/plugin/';
        $path1 = $path . 'config/' . $plugin->name . '.json';
        if(is_file($path1)){
            delFile($path1);
        }

        $dir1 = $path . 'model/' . $plugin->name;
        if(file_exists($dir1)) {
            deldir($dir1);
        }

        $dir = $path . 'view/' . $plugin->name;
        if(file_exists($dir)) {
            deldir($dir);
        }

        $path2 = $path . 'route/list/' . $plugin->name . '.json';
        if(is_file($path2)){
            delFile($path2);
        }
        $path3 = $path . 'controller/' .$plugin->name;
        if(file_exists($path3)){
            deldir($path3);
        }
        /*删除现有插件end*/

        $plugin_url = app()->getRootPath().'/plugin';
        $get_folders = folder_list($plugin_url);
        foreach ($get_folders as $key=>$folder){
            $array = explode('/', $folder['name']);
            if(end($array) != $plugin->name){
                unset($get_folders[$key]);
            }
        }
        $get_folders = array_values($get_folders);
        if(count($get_folders) < 1){
            return msg_error('本地没有插件可更新');
        }
        $res = $this->move_plugin($get_folders,$plugin_url);

        return msg_success('更新成功',$res);
    }

    public function set($id)
    {
        try{
            $plugin = PluginModel::find($id);
            if(!$plugin){
                return msg_error('插件不存在');
            }
            return view('set',['set'=>$plugin->setting,'id'=>$id]);
        }catch (\Exception $e){
            return msg_error($e->getMessage());
        }
    }
    public function update($id)
    {
        try{
            $plugin = PluginModel::find($id);
            if(!$plugin){
                return msg_error('插件不存在');
            }
            $field = input();

            $setting = $plugin->setting;
            foreach ($setting as $key=> $item){
                if(isset($field[$key])){
                    $setting[$key]['value']=$field[$key];
                }
            }
            if(isset($field['frozen'])){
                $plugin->frozen = $field['frozen'];
            }
            $plugin->setting = $setting;
            $info = $plugin->save();
            return return_true_or_false($info,'设置成功');

        }catch (\Exception $e){
            return msg_error($e->getMessage());
        }
    }
    public function set_store($id)
    {
        try{
            $plugin = PluginModel::find($id);
            if(!$plugin){
                return msg_error('插件不存在');
            }
            $field = $this->request->only(['name','key']);

            $setting = $plugin->setting;

            if(isset($setting[$field['key']])){
                return msg_error('唯一值已存在');
            }

            $setting[$field['key']] = [
                'name'=>$field['key'],
                'value'=>''
            ];
            $plugin->setting = $setting;
            $info = $plugin->save();
            return return_true_or_false($info,'新增成功');

        }catch (\Exception $e){
            return msg_error($e->getMessage());
        }
    }
    public function set_delete($id,$key)
    {
        try{
            $plugin = PluginModel::find($id);
            if(!$plugin){
                return msg_error('插件不存在');
            }

            $setting = $plugin->setting;

            if(!isset($setting[$key])){
                return msg_error('配置不存在');
            }
            unset($setting[$key]);
            $plugin->setting = $setting;
            $info = $plugin->save();
            return return_true_or_false($info,'删除成功');

        }catch (\Exception $e){
            return msg_error($e->getMessage());
        }
    }

    public function delete($id)
    {
        try{
            $plugin = PluginModel::find($id);
            if(!$plugin){
                return msg_error('插件不存在');
            }
            $path = app()->getRootPath() . 'app/plugin/';
            $staticPath = app()->getRootPath() . 'public/plugin/';
            $path1 = $path . 'config/' . $plugin->name . '.json';
            if(is_file($path1)){
                delFile($path1);
            }

            $dir1 = $path . 'model/' . $plugin->name;
            if(file_exists($dir1)) {
                deldir($dir1);
            }

            $dir = $path . 'view/' . $plugin->name;
            if(file_exists($dir)) {
                deldir($dir);
            }

            $filename = $staticPath . $plugin->name;
            if(file_exists($filename)){
                deldir($filename);
            }
            $path2 = $path . 'route/list/' . $plugin->name . '.json';
            if(is_file($path2)){
                delFile($path2);
            }
            $path3 = $path . 'controller/' . $plugin->name;
            if(file_exists($path3)){
                deldir($path3);
            }

            $info = $plugin->deleteAndLog();
            return return_true_or_false($info,'删除成功');
        }catch (\Exception $e){
            return msg_error($e->getMessage());
        }
    }

}